package com.example.ntweixin.service;

import com.example.ntweixin.dao.WeixinJsapiTicketLogDao;
import com.example.ntweixin.dto.wx.JsapiTicketDto;
import com.example.ntweixin.entity.WeixinJsapiTicketLog;
import com.example.ntweixin.exception.ServerException;
import com.example.ntweixin.utils.HttpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.example.ntweixin.entity.WeixinJsapiTicket;
import com.example.ntweixin.dao.WeixinJsapiTicketDao;

@Service
public class WeixinJsapiTicketService {

    private static final Logger logger = LoggerFactory.getLogger(WeixinJsapiTicketService.class);
    @Autowired
    private WeixinConf weixinConf;
    @Autowired
    private WeixinJsapiTicketDao weixinJsapiTicketDao;
    @Autowired
    private WeixinJsapiTicketLogDao weixinJsapiTicketLogDao;
    @Autowired
    private WeixinAccessTokenService weixinAccessTokenService;

    public int insert(WeixinJsapiTicket pojo) {
        return weixinJsapiTicketDao.insert(pojo);
    }

    public int insertSelective(WeixinJsapiTicket pojo) {
        return weixinJsapiTicketDao.insertSelective(pojo);
    }

    public int insertList(List<WeixinJsapiTicket> pojos) {
        return weixinJsapiTicketDao.insertList(pojos);
    }

    public int update(WeixinJsapiTicket pojo) {
        return weixinJsapiTicketDao.update(pojo);
    }


    // ----------------------------------------------------------------------------------------------
    public String getJsapiTicket() throws ServerException {
        String jsapiTicket = "";
        logger.info("读取数据库中的accessToken");


        WeixinJsapiTicket ticket = weixinJsapiTicketDao.getById(weixinConf.getPublicId());
        if (ticket == null) {
            // 数据库中没有ticket信息，从微信服务器获取ticket
            logger.info("数据库中没有ticket信息，从微信服务器获取ticket");
            JsapiTicketDto dto = getTicketFromWeixinServer();
            ticket = dtoToEntity(dto);
            ticket.setWeixinPublicId(weixinConf.getPublicId());
            WeixinJsapiTicketLog ticketLog = dtoToJsapiTicketLog(dto);
            weixinJsapiTicketDao.insert(ticket);
            weixinJsapiTicketLogDao.insert(ticketLog);
        } else {
            // 判断是否过期
            if (isExpires(ticket)) {
                // 过期，重新获取ticket
                logger.info("过期，重新获取ticket");
                Long id = ticket.getId();
                JsapiTicketDto dto = getTicketFromWeixinServer();
                ticket = dtoToEntity(dto);
                WeixinJsapiTicketLog ticketLog = dtoToJsapiTicketLog(dto);

                ticket.setId(id);
                weixinJsapiTicketDao.update(ticket);
                weixinJsapiTicketLogDao.insert(ticketLog);
            }
        }
        jsapiTicket = ticket.getJsapiTicket();
        return jsapiTicket;
    }

    private JsapiTicketDto getTicketFromWeixinServer() throws ServerException {
        String accessToken = weixinAccessTokenService.getAccessToken();

        // https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=NRyi9YnmjZU_VsTUSFNsOxp3GfY5ZexbnbZPMX0hAC7Zcdrn20_m7qFzHTcsaDf99g83W7K_uAwxuwyHtcrqJRlYps2FlBnNJQUauiznTdk&type=jsapi
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";

        // {"errcode":0,"errmsg":"ok","ticket":"bxLdikRXVbTPdHSM05e5u3tgwh7S8MpcDcXHS8MO__V-YjhJbpE7gnR72fmm77V2b_t_LGHFWKI-i2V4DZRWsg","expires_in":7200}
        String body = HttpUtil.httpGet(url);

        ObjectMapper mapper = new ObjectMapper();
        JsapiTicketDto bean = null;
        try {
            bean = mapper.readValue(body, JsapiTicketDto.class);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw new ServerException(HttpStatus.INTERNAL_SERVER_ERROR, "从微信服务器读取JsapiTicket时，将json转换为对象(" + JsapiTicketDto.class + ")报错。");
        }
        if (bean.getErrcode().longValue() == 0L && "ok".equals(bean.getErrmsg())) {
            return bean;
        } else {
            throw new ServerException(bean.getErrcode().toString(), bean.getErrmsg());
        }

    }

    private WeixinJsapiTicket dtoToEntity(JsapiTicketDto dto) {
        WeixinJsapiTicket t = new WeixinJsapiTicket();
        t.setCreateDate(new Date());
        t.setUpdateDate(new Date());
        t.setExpiresIn(Long.valueOf(dto.getExpires_in()));
        t.setJsapiTicket(dto.getTicket());
        return t;
    }

    private WeixinJsapiTicketLog dtoToJsapiTicketLog(JsapiTicketDto dto) {
        WeixinJsapiTicketLog t = new WeixinJsapiTicketLog();
        t.setCreateDate(new Date());
        t.setExpiresIn(Long.valueOf(dto.getExpires_in()));
        t.setJsapiTicket(dto.getTicket());
        t.setErrcode(dto.getErrcode().toString());
        t.setErrmsg(dto.getErrmsg());
        t.setWeixinPublicId(weixinConf.getPublicId());

        return t;
    }

    /**
     * 是否过期
     *
     * @param ticket
     * @return
     */
    public boolean isExpires(WeixinJsapiTicket ticket) {
        boolean isExpires = false;

        Calendar sendedCal = Calendar.getInstance();//
        sendedCal.setTime(ticket.getUpdateDate());
        sendedCal.add(Calendar.SECOND, ticket.getExpiresIn().intValue() - 120);// 提前2分钟过期

        Calendar nowCal = Calendar.getInstance();
        nowCal.setTime(new Date());

        if (sendedCal.before(nowCal)) {
            isExpires = true;
        }

        return isExpires;
    }
}
